import 'dart:convert';

import 'package:amap/amap.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';

import 'poi_bean.dart';

class PoiSearch {
  static const urlSearchText = "https://restapi.amap.com/v3/place/text?";
  static const urlSearchAround = "https://restapi.amap.com/v3/place/around?";
  static const urlPOIDetail = "https://restapi.amap.com/v3/place/detail?";

  static const demoKey = "39ab9eb8a3773d7dd5a8d8ddd7b3b110";

  static Future<SearchTextResult> searchText(SearchTextOptions options) async {
    final url = "$urlSearchText${options?.toMap()?.asUrlParameters()}";
    print(url);
    final result = await get(url);
    if (result.statusCode == 200) {
      try {
        return SearchTextResult.fromJson(jsonDecode(result.body));
      } catch (e) {
        print(e);
        return null;
      }
    } else {
      return null;
    }
  }

  static Future<SearchTextResult> searchAround(
      SearchAroundOptions options) async {
    final url = "$urlSearchAround${options?.toMap()?.asUrlParameters()}";
    print(url);
    final result = await get(url);
    if (result.statusCode == 200) {
      try {
        return SearchTextResult.fromJson(jsonDecode(result.body));
      } catch (e) {
        print(e);
        return null;
      }
    } else {
      return null;
    }
  }

  static Future getPoiDetail() {}
}

extension MapExtensions on Map<String, dynamic> {
  String asUrlParameters() {
    final sb = StringBuffer();
    forEach((key, value) {
      if (value != null) {
        sb.write("$key=$value&");
      }
    });
    final params = sb.toString();
    if (params.isNotEmpty && params.endsWith("&")) {
      return params.substring(0, params.length - 1);
    } else {
      return params;
    }
  }
}

///https://lbs.amap.com/api/webservice/guide/api/search#text
class SearchTextOptions {
//  key
//  请求服务权限标识
//  用户在高德地图官网申请Web服务API类型KEY
//  必填
//  无
  String key;

//  keywords
//  查询关键字
//  规则： 多个关键字用“|”分割
//  若不指定city，并且搜索的为泛词（例如“美食”）的情况下，返回的内容为城市列表以及此城市内有多少结果符合要求。
//  必填
//  (keywords和types两者至少必选其一)
//  无
  List<String> keywords;

//  types
//  查询POI类型
//  可选值：分类代码 或 汉字（若用汉字，请严格按照附件之中的汉字填写）
//
//  分类代码由六位数字组成，一共分为三个部分，前两个数字代表大类；中间两个数字代表中类；最后两个数字代表小类。
//  若指定了某个大类，则所属的中类、小类都会被显示。
//  例如：010000为汽车服务（大类）
//  010100为加油站（中类）
//  010101为中国石化（小类）
//  010900为汽车租赁（中类）
//  010901为汽车租赁还车（小类）
//  当指定010000，则010100等中类、010101等小类都会被包含，当指定010900，则010901等小类都会被包含。
//  下载POI分类编码和城市编码表
//
//  若不指定city，返回的内容为城市列表以及此城市内有多少结果符合要求。
//  当您的keywords和types都是空时，默认指定types为120000（商务住宅）&150000（交通设施服务）
//  必填
//  (keywords和types两者至少必选其一)
  String types;

//  无
//  city
//  查询城市
//  可选值：城市中文、中文全拼、citycode、adcode
//  如：北京/beijing/010/110000
//  填入此参数后，会尽量优先返回此城市数据，但是不一定仅局限此城市结果，若仅需要某个城市数据请调用citylimit参数。
//  如：在深圳市搜天安门，返回北京天安门结果。
//  可选
//  无（全国范围内搜索）
  String city;

//  citylimit
//  仅返回指定城市数据
//  可选值：true/false
//  可选
//  false
  bool citylimit;

//  children
//  是否按照层级展示子POI数据
//  可选值：children=1
//  当为0的时候，子POI都会显示。
//  当为1的时候，子POI会归类到父POI之中。
//
//  仅在extensions=all的时候生效
//  可选
//  0
  int children;

//  offset
//  每页记录数据
//  强烈建议不超过25，若超过25可能造成访问报错
//  可选
//  20
  int offset;

//  page
//  当前页数
//  最大翻页数100
//  可选
//  1
  int page;

//  extensions
//  返回结果控制
//  此项默认返回基本地址信息；取值为all返回地址信息、附近POI、道路以及道路交叉口信息。
//  可选
//  base
  String extensions;

//  sig
//  数字签名
//  数字签名获取和使用方法
//  可选
//  无
  String sig;

//  output
//  返回数据格式类型
//  可选值：JSON，XML
//  可选
//  JSON
  String output;

  SearchTextOptions({
    @required this.key,
    this.keywords,
    this.types,
    this.city,
    this.citylimit,
    this.children,
    this.page = 1,
    this.offset = 20,
    this.extensions,
    this.sig,
    this.output,
  });

  Map<String, dynamic> toMap() {
    return {
      "key": key,
      "keywords": keywords?.join("|"),
      "types": types,
      "city": city,
      "citylimit": citylimit,
      "children": children,
      "page": page,
      "offset": offset,
      "extensions": extensions,
      "sig": sig,
      "output": output,
    };
  }
}

///https://lbs.amap.com/api/webservice/guide/api/search#text
class SearchAroundOptions {
//  key
//  请求服务权限标识
//  用户在高德地图官网申请Web服务API类型KEY
//  必填
//  无
  String key;

//  location
//  中心点坐标
//  规则： 经度和纬度用","分割，经度在前，纬度在后，经纬度小数点后不得超过6位
  LatLng location;

//  radius
//  查询半径
//  取值范围:0-50000。规则：大于50000按默认值，单位：米
  double radius;

//  sortrule
//  排序规则
//  规定返回结果的排序规则。
//  按距离排序：distance；综合排序：weight
//  可选
//  distance

  String sortRule;

//  keywords
//  查询关键字
//  规则： 多个关键字用“|”分割
//  若不指定city，并且搜索的为泛词（例如“美食”）的情况下，返回的内容为城市列表以及此城市内有多少结果符合要求。
//  必填
//  (keywords和types两者至少必选其一)
//  无
  List<String> keywords;

//  types
//  查询POI类型
//  可选值：分类代码 或 汉字（若用汉字，请严格按照附件之中的汉字填写）
//
//  分类代码由六位数字组成，一共分为三个部分，前两个数字代表大类；中间两个数字代表中类；最后两个数字代表小类。
//  若指定了某个大类，则所属的中类、小类都会被显示。
//  例如：010000为汽车服务（大类）
//  010100为加油站（中类）
//  010101为中国石化（小类）
//  010900为汽车租赁（中类）
//  010901为汽车租赁还车（小类）
//  当指定010000，则010100等中类、010101等小类都会被包含，当指定010900，则010901等小类都会被包含。
//  下载POI分类编码和城市编码表
//
//  若不指定city，返回的内容为城市列表以及此城市内有多少结果符合要求。
//  当您的keywords和types都是空时，默认指定types为120000（商务住宅）&150000（交通设施服务）
//  必填
//  (keywords和types两者至少必选其一)
  String types;

//  无
//  city
//  查询城市
//  可选值：城市中文、中文全拼、citycode、adcode
//  如：北京/beijing/010/110000
//  填入此参数后，会尽量优先返回此城市数据，但是不一定仅局限此城市结果，若仅需要某个城市数据请调用citylimit参数。
//  如：在深圳市搜天安门，返回北京天安门结果。
//  可选
//  无（全国范围内搜索）
  String city;

//  citylimit
//  仅返回指定城市数据
//  可选值：true/false
//  可选
//  false
  bool citylimit;

//  children
//  是否按照层级展示子POI数据
//  可选值：children=1
//  当为0的时候，子POI都会显示。
//  当为1的时候，子POI会归类到父POI之中。
//
//  仅在extensions=all的时候生效
//  可选
//  0
  int children;

//  offset
//  每页记录数据
//  强烈建议不超过25，若超过25可能造成访问报错
//  可选
//  20
  int offset;

//  page
//  当前页数
//  最大翻页数100
//  可选
//  1
  int page;

//  extensions
//  返回结果控制
//  此项默认返回基本地址信息；取值为all返回地址信息、附近POI、道路以及道路交叉口信息。
//  可选
//  base
  String extensions;

//  sig
//  数字签名
//  数字签名获取和使用方法
//  可选
//  无
  String sig;

//  output
//  返回数据格式类型
//  可选值：JSON，XML
//  可选
//  JSON
  String output;

  SearchAroundOptions({
    @required this.key,
    this.location,
    this.radius,
    this.sortRule,
    this.keywords,
    this.types,
    this.city,
    this.citylimit,
    this.children,
    this.page = 1,
    this.offset = 20,
    this.extensions,
    this.sig,
    this.output,
  });

  Map<String, dynamic> toMap() {
    return {
      "key": key,
      "location": "${location.longitude},${location.latitude}",
      "radius": radius > 50000 ? 50000 : radius,
      "keywords": keywords?.join("|"),
      "sortrule": sortRule,
      "types": types,
      "city": city,
      "citylimit": citylimit,
      "children": children,
      "page": page,
      "offset": offset,
      "extensions": extensions,
      "sig": sig,
      "output": output,
    };
  }
}
